/*
* Copyright 2014 - 2017 Blazebit.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.blazebit.persistence.criteria.impl;
import com.blazebit.persistence.CriteriaBuilderFactory;
import com.blazebit.persistence.criteria.BlazeCollectionJoin;
import com.blazebit.persistence.criteria.BlazeCriteriaBuilder;
import com.blazebit.persistence.criteria.BlazeCriteriaDelete;
import com.blazebit.persistence.criteria.BlazeCriteriaQuery;
import com.blazebit.persistence.criteria.BlazeCriteriaUpdate;
import com.blazebit.persistence.criteria.BlazeJoin;
import com.blazebit.persistence.criteria.BlazeListJoin;
import com.blazebit.persistence.criteria.BlazeMapJoin;
import com.blazebit.persistence.criteria.BlazeOrder;
import com.blazebit.persistence.criteria.BlazeRoot;
import com.blazebit.persistence.criteria.BlazeSetJoin;
import com.blazebit.persistence.criteria.impl.expression.AbstractExpression;
import com.blazebit.persistence.criteria.impl.expression.AbstractPredicate;
import com.blazebit.persistence.criteria.impl.expression.BetweenPredicate;
import com.blazebit.persistence.criteria.impl.expression.BinaryArithmeticExpression;
import com.blazebit.persistence.criteria.impl.expression.BooleanExpressionPredicate;
import com.blazebit.persistence.criteria.impl.expression.BooleanLiteralPredicate;
import com.blazebit.persistence.criteria.impl.expression.ComparisonPredicate;
import com.blazebit.persistence.criteria.impl.expression.ComparisonPredicate.ComparisonOperator;
import com.blazebit.persistence.criteria.impl.expression.CompoundPredicate;
import com.blazebit.persistence.criteria.impl.expression.CompoundSelectionImpl;
import com.blazebit.persistence.criteria.impl.expression.ExistsPredicate;
import com.blazebit.persistence.criteria.impl.expression.GeneralCaseExpression;
import com.blazebit.persistence.criteria.impl.expression.InPredicate;
import com.blazebit.persistence.criteria.impl.expression.IsEmptyPredicate;
import com.blazebit.persistence.criteria.impl.expression.IsNullPredicate;
import com.blazebit.persistence.criteria.impl.expression.LikePredicate;
import com.blazebit.persistence.criteria.impl.expression.LiteralExpression;
import com.blazebit.persistence.criteria.impl.expression.MemberOfPredicate;
import com.blazebit.persistence.criteria.impl.expression.NotPredicate;
import com.blazebit.persistence.criteria.impl.expression.NullLiteralExpression;
import com.blazebit.persistence.criteria.impl.expression.ParameterExpressionImpl;
import com.blazebit.persistence.criteria.impl.expression.QuantifiableSubqueryExpression;
import com.blazebit.persistence.criteria.impl.expression.SimpleCaseExpression;
import com.blazebit.persistence.criteria.impl.expression.UnaryMinusExpression;
import com.blazebit.persistence.criteria.impl.expression.function.AbsFunction;
import com.blazebit.persistence.criteria.impl.expression.function.AggregationFunction;
import com.blazebit.persistence.criteria.impl.expression.function.CoalesceFunction;
import com.blazebit.persistence.criteria.impl.expression.function.ConcatFunction;
import com.blazebit.persistence.criteria.impl.expression.function.CurrentDateFunction;
import com.blazebit.persistence.criteria.impl.expression.function.CurrentTimeFunction;
import com.blazebit.persistence.criteria.impl.expression.function.CurrentTimestampFunction;
import com.blazebit.persistence.criteria.impl.expression.function.FunctionExpressionImpl;
import com.blazebit.persistence.criteria.impl.expression.function.FunctionFunction;
import com.blazebit.persistence.criteria.impl.expression.function.LengthFunction;
import com.blazebit.persistence.criteria.impl.expression.function.LocateFunction;
import com.blazebit.persistence.criteria.impl.expression.function.LowerFunction;
import com.blazebit.persistence.criteria.impl.expression.function.NullifFunction;
import com.blazebit.persistence.criteria.impl.expression.function.SizeFunction;
import com.blazebit.persistence.criteria.impl.expression.function.SqrtFunction;
import com.blazebit.persistence.criteria.impl.expression.function.SubstringFunction;
import com.blazebit.persistence.criteria.impl.expression.function.TrimFunction;
import com.blazebit.persistence.criteria.impl.expression.function.UpperFunction;
import com.blazebit.persistence.criteria.impl.path.AbstractJoin;
import com.blazebit.persistence.criteria.impl.path.AbstractPath;
import com.blazebit.persistence.criteria.impl.path.CollectionAttributeJoin;
import com.blazebit.persistence.criteria.impl.path.ListAttributeJoin;
import com.blazebit.persistence.criteria.impl.path.MapAttributeJoin;
import com.blazebit.persistence.criteria.impl.path.PluralAttributePath;
import com.blazebit.persistence.criteria.impl.path.RootImpl;
import com.blazebit.persistence.criteria.impl.path.SetAttributeJoin;
import com.blazebit.persistence.impl.EntityMetamodel;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Tuple;
import javax.persistence.criteria.CollectionJoin;
import javax.persistence.criteria.CompoundSelection;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.ListJoin;
import javax.persistence.criteria.MapJoin;
import javax.persistence.criteria.ParameterExpression;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Predicate.BooleanOperator;
import javax.persistence.criteria.Root;
import javax.persistence.criteria.Selection;
import javax.persistence.criteria.SetJoin;
import javax.persistence.criteria.Subquery;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author Christian Beikov
* @since 1.2.0
*/
public class BlazeCriteriaBuilderImpl implements BlazeCriteriaBuilder, Serializable {
private static final long serialVersionUID = 1L;
// TODO: make configurable
private static final boolean DO_WRAPPING = true;
private final EntityManager entityManager;
private final EntityMetamodel metamodel;
private final CriteriaBuilderFactory cbf;
public BlazeCriteriaBuilderImpl(EntityManager entityManager, CriteriaBuilderFactory cbf) {
this.entityManager = entityManager;
this.metamodel = cbf.getService(EntityMetamodel.class);
this.cbf = cbf;
}
public EntityManager getEntityManager() {
return entityManager;
}
public EntityManagerFactory getEntityManagerFactory() {
return getEntityManager().getEntityManagerFactory();
}
public EntityMetamodel getEntityMetamodel() {
return metamodel;
}
public CriteriaBuilderFactory getCriteriaBuilderFactory() {
return cbf;
}
public <T extends AbstractPredicate> AbstractPredicate negate(T predicate) {
if (DO_WRAPPING) {
return new NotPredicate(this, predicate);
} else {
return predicate.copyNegated();
}
}
@Override
public BlazeCriteriaQuery<Object> createQuery() {
return new BlazeCriteriaQueryImpl<Object>(this, Object.class);
}
@Override
public <T> BlazeCriteriaQuery<T> createQuery(Class<T> resultClass) {
return new BlazeCriteriaQueryImpl<T>(this, resultClass);
}
@Override
public BlazeCriteriaQuery<Tuple> createTupleQuery() {
return new BlazeCriteriaQueryImpl<Tuple>(this, Tuple.class);
}
@Override
public <T> BlazeCriteriaUpdate<T> createCriteriaUpdate(Class<T> targetEntity) {
return new BlazeCriteriaUpdateImpl<T>(this, targetEntity, null);
}
@Override
public <T> BlazeCriteriaUpdate<T> createCriteriaUpdate(Class<T> targetEntity, String alias) {
return new BlazeCriteriaUpdateImpl<T>(this, targetEntity, alias);
}
@Override
public <T> BlazeCriteriaDelete<T> createCriteriaDelete(Class<T> targetEntity) {
return new BlazeCriteriaDeleteImpl<T>(this, targetEntity, null);
}
@Override
public <T> BlazeCriteriaDelete<T> createCriteriaDelete(Class<T> targetEntity, String alias) {
return new BlazeCriteriaDeleteImpl<T>(this, targetEntity, alias);
}
/**********************
* Selection stuff
**********************/
private List<Selection<?>> wrapSelectionItems(List<Selection<?>> selections) {
List<Selection<?>> copy = null;
for (int i = 0; i < selections.size(); i++) {
Selection<?> selection = selections.get(i);
if (selection.isCompoundSelection()) {
// TODO: rethink if this restriction shouldn't be relaxed
if (selection.getJavaType().isArray()) {
throw new IllegalArgumentException("Illegal array selection in multiselect selections");
}
if (Tuple.class.isAssignableFrom(selection.getJavaType())) {
throw new IllegalArgumentException("Illegal tuple selection in multiselect selections");
}
}
Selection<?> copySelection = wrapSelection(selection);
if (copy != null) {
copy.add(copySelection);
} else if (copySelection != selection) {
copy = new ArrayList<Selection<?>>();
for (int j = 0; j < i; j++) {
copy.add(selections.get(j));
}
copy.add(copySelection);
}
}
if (copy != null) {
return copy;
}
return selections;
}
@SuppressWarnings({"unchecked"})
public <T> Selection<? extends T> wrapSelection(Selection<? extends T> selection) {
if (selection instanceof Predicate) {
return (Selection<? extends T>) selectCase().when((Predicate) selection, literal(true)).otherwise(literal(false));
}
return selection;
}
@Override
public CompoundSelection<Tuple> tuple(Selection<?>... selections) {
return tuple(Arrays.asList(selections));
}
public CompoundSelection<Tuple> tuple(List<Selection<?>> selections) {
return new CompoundSelectionImpl<Tuple>(this, Tuple.class, wrapSelectionItems(selections));
}
@Override
public CompoundSelection<Object[]> array(Selection<?>... selections) {
return array(Arrays.asList(selections));
}
public CompoundSelection<Object[]> array(List<Selection<?>> selections) {
return array(Object[].class, selections);
}
public <Y> CompoundSelection<Y> array(Class<Y> type, List<Selection<?>> selections) {
return new CompoundSelectionImpl<Y>(this, type, wrapSelectionItems(selections));
}
@Override
public <Y> CompoundSelection<Y> construct(Class<Y> result, Selection<?>... selections) {
return construct(result, Arrays.asList(selections));
}
public <Y> CompoundSelection<Y> construct(Class<Y> result, List<Selection<?>> selections) {
return new CompoundSelectionImpl<Y>(this, result, wrapSelectionItems(selections));
}
/**********************
* Order by stuff
**********************/
@Override
public BlazeOrder asc(Expression<?> x) {
return new OrderImpl(x, true, false);
}
@Override
public BlazeOrder desc(Expression<?> x) {
return new OrderImpl(x, false, false);
}
@Override
public BlazeOrder asc(Expression<?> x, boolean nullsFirst) {
return new OrderImpl(x, true, nullsFirst);
}
@Override
public BlazeOrder desc(Expression<?> x, boolean nullsFirst) {
return new OrderImpl(x, false, nullsFirst);
}
/**********************
* Predicates
**********************/
public Predicate wrap(Expression<Boolean> expression) {
if (expression instanceof Predicate) {
return (Predicate) expression;
} else if (expression instanceof AbstractPath<?>) {
return equal(expression, literal(Boolean.TRUE));
} else {
return new BooleanExpressionPredicate(this, false, expression);
}
}
@Override
public Predicate not(Expression<Boolean> expression) {
return wrap(expression).not();
}
@Override
public Predicate and(Expression<Boolean> x, Expression<Boolean> y) {
return new CompoundPredicate(this, BooleanOperator.AND, x, y);
}
@Override
public Predicate or(Expression<Boolean> x, Expression<Boolean> y) {
return new CompoundPredicate(this, BooleanOperator.OR, x, y);
}
@Override
public Predicate and(Predicate... restrictions) {
return new CompoundPredicate(this, BooleanOperator.AND, restrictions);
}
@Override
public Predicate or(Predicate... restrictions) {
return new CompoundPredicate(this, BooleanOperator.OR, restrictions);
}
@Override
public Predicate conjunction() {
return new CompoundPredicate(this, BooleanOperator.AND);
}
@Override
public Predicate disjunction() {
return new CompoundPredicate(this, BooleanOperator.OR);
}
@Override
public Predicate isTrue(Expression<Boolean> expression) {
if (CompoundPredicate.class.isInstance(expression)) {
final CompoundPredicate predicate = (CompoundPredicate) expression;
if (predicate.getExpressions().size() == 0) {
return new BooleanLiteralPredicate(this, predicate.getOperator() == BooleanOperator.AND);
}
return predicate;
} else if (Predicate.class.isInstance(expression)) {
return (Predicate) expression;
}
return equal(expression, literal(Boolean.TRUE));
}
@Override
public Predicate isFalse(Expression<Boolean> expression) {
if (CompoundPredicate.class.isInstance(expression)) {
final CompoundPredicate predicate = (CompoundPredicate) expression;
if (predicate.getExpressions().size() == 0) {
return new BooleanLiteralPredicate(this, predicate.getOperator() == BooleanOperator.OR);
}
return predicate.not();
} else if (Predicate.class.isInstance(expression)) {
final Predicate predicate = (Predicate) expression;
return predicate.not();
}
return equal(expression, literal(Boolean.FALSE));
}
@Override
public Predicate isNull(Expression<?> x) {
return new IsNullPredicate(this, false, x);
}
@Override
public Predicate isNotNull(Expression<?> x) {
return new IsNullPredicate(this, true, x);
}
@Override
public Predicate equal(Expression<?> x, Expression<?> y) {
return new ComparisonPredicate(this, ComparisonOperator.EQUAL, x, y);
}
@Override
public Predicate notEqual(Expression<?> x, Expression<?> y) {
return new ComparisonPredicate(this, ComparisonOperator.NOT_EQUAL, x, y);
}
@Override
public Predicate equal(Expression<?> x, Object y) {
return new ComparisonPredicate(this, ComparisonOperator.EQUAL, x, y);
}
@Override
public Predicate notEqual(Expression<?> x, Object y) {
return new ComparisonPredicate(this, ComparisonOperator.NOT_EQUAL, x, y);
}
@Override
public <Y extends Comparable<? super Y>> Predicate greaterThan(Expression<? extends Y> x, Expression<? extends Y> y) {
return new ComparisonPredicate(this, ComparisonOperator.GREATER_THAN, x, y);
}
@Override
public <Y extends Comparable<? super Y>> Predicate lessThan(Expression<? extends Y> x, Expression<? extends Y> y) {
return new ComparisonPredicate(this, ComparisonOperator.LESS_THAN, x, y);
}
@Override
public <Y extends Comparable<? super Y>> Predicate greaterThanOrEqualTo(Expression<? extends Y> x, Expression<? extends Y> y) {
return new ComparisonPredicate(this, ComparisonOperator.GREATER_THAN_OR_EQUAL, x, y);
}
@Override
public <Y extends Comparable<? super Y>> Predicate lessThanOrEqualTo(Expression<? extends Y> x, Expression<? extends Y> y) {
return new ComparisonPredicate(this, ComparisonOperator.LESS_THAN_OR_EQUAL, x, y);
}
@Override
public <Y extends Comparable<? super Y>> Predicate greaterThan(Expression<? extends Y> x, Y y) {
return new ComparisonPredicate(this, ComparisonOperator.GREATER_THAN, x, y);
}
@Override
public <Y extends Comparable<? super Y>> Predicate lessThan(Expression<? extends Y> x, Y y) {
return new ComparisonPredicate(this, ComparisonOperator.LESS_THAN, x, y);
}
@Override
public <Y extends Comparable<? super Y>> Predicate greaterThanOrEqualTo(Expression<? extends Y> x, Y y) {
return new ComparisonPredicate(this, ComparisonOperator.GREATER_THAN_OR_EQUAL, x, y);
}
@Override
public <Y extends Comparable<? super Y>> Predicate lessThanOrEqualTo(Expression<? extends Y> x, Y y) {
return new ComparisonPredicate(this, ComparisonOperator.LESS_THAN_OR_EQUAL, x, y);
}
@Override
public Predicate gt(Expression<? extends Number> x, Expression<? extends Number> y) {
return new ComparisonPredicate(this, ComparisonOperator.GREATER_THAN, x, y);
}
@Override
public Predicate lt(Expression<? extends Number> x, Expression<? extends Number> y) {
return new ComparisonPredicate(this, ComparisonOperator.LESS_THAN, x, y);
}
@Override
public Predicate ge(Expression<? extends Number> x, Expression<? extends Number> y) {
return new ComparisonPredicate(this, ComparisonOperator.GREATER_THAN_OR_EQUAL, x, y);
}
@Override
public Predicate le(Expression<? extends Number> x, Expression<? extends Number> y) {
return new ComparisonPredicate(this, ComparisonOperator.LESS_THAN_OR_EQUAL, x, y);
}
@Override
public Predicate gt(Expression<? extends Number> x, Number y) {
return new ComparisonPredicate(this, ComparisonOperator.GREATER_THAN, x, y);
}
@Override
public Predicate lt(Expression<? extends Number> x, Number y) {
return new ComparisonPredicate(this, ComparisonOperator.LESS_THAN, x, y);
}
@Override
public Predicate ge(Expression<? extends Number> x, Number y) {
return new ComparisonPredicate(this, ComparisonOperator.GREATER_THAN_OR_EQUAL, x, y);
}
@Override
public Predicate le(Expression<? extends Number> x, Number y) {
return new ComparisonPredicate(this, ComparisonOperator.LESS_THAN_OR_EQUAL, x, y);
}
@Override
public <Y extends Comparable<? super Y>> Predicate between(Expression<? extends Y> expression, Y lowerBound, Y upperBound) {
return new BetweenPredicate<Y>(this, false, expression, lowerBound, upperBound);
}
@Override
public <Y extends Comparable<? super Y>> Predicate between(Expression<? extends Y> expression, Expression<? extends Y> lowerBound, Expression<? extends Y> upperBound) {
return new BetweenPredicate<Y>(this, false, expression, lowerBound, upperBound);
}
@Override
public <T> In<T> in(Expression<? extends T> expression) {
return new InPredicate<T>(this, expression);
}
public <T> In<T> in(Expression<? extends T> expression, Expression<? extends T>... values) {
return new InPredicate<T>(this, expression, values);
}
public <T> In<T> in(Expression<? extends T> expression, T... values) {
return new InPredicate<T>(this, expression, values);
}
public <T> In<T> in(Expression<? extends T> expression, Collection<T> values) {
return new InPredicate<T>(this, expression, values);
}
@Override
public Predicate like(Expression<String> matchExpression, Expression<String> pattern) {
return new LikePredicate(this, false, matchExpression, pattern);
}
@Override
public Predicate like(Expression<String> matchExpression, Expression<String> pattern, Expression<Character> escapeCharacter) {
return new LikePredicate(this, false, matchExpression, pattern, escapeCharacter);
}
@Override
public Predicate like(Expression<String> matchExpression, Expression<String> pattern, char escapeCharacter) {
return new LikePredicate(this, false, matchExpression, pattern, escapeCharacter);
}
@Override
public Predicate like(Expression<String> matchExpression, String pattern) {
return new LikePredicate(this, false, matchExpression, pattern);
}
@Override
public Predicate like(Expression<String> matchExpression, String pattern, Expression<Character> escapeCharacter) {
return new LikePredicate(this, false, matchExpression, pattern, escapeCharacter);
}
@Override
public Predicate like(Expression<String> matchExpression, String pattern, char escapeCharacter) {
return new LikePredicate(this, false, matchExpression, pattern, escapeCharacter);
}
@Override
public Predicate notLike(Expression<String> matchExpression, Expression<String> pattern) {
return new LikePredicate(this, true, matchExpression, pattern);
}
@Override
public Predicate notLike(Expression<String> matchExpression, Expression<String> pattern, Expression<Character> escapeCharacter) {
return new LikePredicate(this, true, matchExpression, pattern, escapeCharacter);
}
@Override
public Predicate notLike(Expression<String> matchExpression, Expression<String> pattern, char escapeCharacter) {
return new LikePredicate(this, true, matchExpression, pattern, escapeCharacter);
}
@Override
public Predicate notLike(Expression<String> matchExpression, String pattern) {
return new LikePredicate(this, true, matchExpression, pattern);
}
@Override
public Predicate notLike(Expression<String> matchExpression, String pattern, Expression<Character> escapeCharacter) {
return new LikePredicate(this, true, matchExpression, pattern, escapeCharacter);
}
@Override
public Predicate notLike(Expression<String> matchExpression, String pattern, char escapeCharacter) {
return new LikePredicate(this, true, matchExpression, pattern, escapeCharacter);
}
/**********************
* Parameter and literal
**********************/
@Override
public <T> ParameterExpression<T> parameter(Class<T> paramClass) {
return new ParameterExpressionImpl<T>(this, paramClass);
}
@Override
public <T> ParameterExpression<T> parameter(Class<T> paramClass, String name) {
return new ParameterExpressionImpl<T>(this, paramClass, name);
}
@Override
public <T> AbstractExpression<T> literal(T value) {
checkValue(value);
return new LiteralExpression<T>(this, value);
}
@Override
public <T> AbstractExpression<T> nullLiteral(Class<T> resultClass) {
return new NullLiteralExpression<T>(this, resultClass);
}
/**********************
* Aggregate functions
**********************/
@Override
public <N extends Number> Expression<Double> avg(Expression<N> x) {
return new AggregationFunction.AVG(this, x);
}
@Override
public <N extends Number> Expression<N> sum(Expression<N> x) {
return new AggregationFunction.SUM<N>(this, x);
}
@Override
public Expression<Long> sumAsLong(Expression<Integer> x) {
return new AggregationFunction.SUM<Long>(this, x, Long.class);
}
@Override
public Expression<Double> sumAsDouble(Expression<Float> x) {
return new AggregationFunction.SUM<Double>(this, x, Double.class);
}
@Override
public <N extends Number> Expression<N> max(Expression<N> x) {
return new AggregationFunction.MAX<N>(this, x);
}
@Override
public <N extends Number> Expression<N> min(Expression<N> x) {
return new AggregationFunction.MIN<N>(this, x);
}
@Override
@SuppressWarnings({"unchecked"})
public <X extends Comparable<? super X>> Expression<X> greatest(Expression<X> x) {
return new AggregationFunction.GREATEST(this, x);
}
@Override
@SuppressWarnings({"unchecked"})
public <X extends Comparable<? super X>> Expression<X> least(Expression<X> x) {
return new AggregationFunction.LEAST(this, x);
}
@Override
public Expression<Long> count(Expression<?> x) {
return new AggregationFunction.COUNT(this, x, false);
}
@Override
public Expression<Long> countDistinct(Expression<?> x) {
return new AggregationFunction.COUNT(this, x, true);
}
/**********************
* Other functions
**********************/
@Override
public <T> Expression<T> function(String name, Class<T> returnType, Expression<?>... arguments) {
return new FunctionExpressionImpl<T>(this, returnType, name, arguments);
}
@Override
public <T> Expression<T> functionFunction(String name, Class<T> returnType, Expression<?>... arguments) {
return new FunctionFunction<T>(this, returnType, name, arguments);
}
@Override
public <N extends Number> Expression<N> abs(Expression<N> expression) {
return new AbsFunction<N>(this, expression);
}
@Override
public Expression<Double> sqrt(Expression<? extends Number> expression) {
return new SqrtFunction(this, expression);
}
@Override
public Expression<java.sql.Date> currentDate() {
return new CurrentDateFunction(this);
}
@Override
public Expression<java.sql.Timestamp> currentTimestamp() {
return new CurrentTimestampFunction(this);
}
@Override
public Expression<java.sql.Time> currentTime() {
return new CurrentTimeFunction(this);
}
@Override
public Expression<String> substring(Expression<String> value, Expression<Integer> start) {
return new SubstringFunction(this, value, start);
}
@Override
public Expression<String> substring(Expression<String> value, int start) {
return new SubstringFunction(this, value, start);
}
@Override
public Expression<String> substring(Expression<String> value, Expression<Integer> start, Expression<Integer> length) {
return new SubstringFunction(this, value, start, length);
}
@Override
public Expression<String> substring(Expression<String> value, int start, int length) {
return new SubstringFunction(this, value, start, length);
}
@Override
public Expression<String> trim(Expression<String> trimSource) {
return new TrimFunction(this, trimSource);
}
@Override
public Expression<String> trim(Trimspec trimspec, Expression<String> trimSource) {
return new TrimFunction(this, trimspec, trimSource);
}
@Override
public Expression<String> trim(Expression<Character> trimCharacter, Expression<String> trimSource) {
return new TrimFunction(this, trimCharacter, trimSource);
}
@Override
public Expression<String> trim(Trimspec trimspec, Expression<Character> trimCharacter, Expression<String> trimSource) {
return new TrimFunction(this, trimspec, trimCharacter, trimSource);
}
@Override
public Expression<String> trim(char trimCharacter, Expression<String> trimSource) {
return new TrimFunction(this, trimCharacter, trimSource);
}
@Override
public Expression<String> trim(Trimspec trimspec, char trimCharacter, Expression<String> trimSource) {
return new TrimFunction(this, trimspec, trimCharacter, trimSource);
}
@Override
public Expression<String> lower(Expression<String> value) {
return new LowerFunction(this, value);
}
@Override
public Expression<String> upper(Expression<String> value) {
return new UpperFunction(this, value);
}
@Override
public Expression<Integer> length(Expression<String> value) {
return new LengthFunction(this, value);
}
@Override
public Expression<Integer> locate(Expression<String> string, Expression<String> pattern) {
return new LocateFunction(this, pattern, string);
}
@Override
public Expression<Integer> locate(Expression<String> string, Expression<String> pattern, Expression<Integer> start) {
return new LocateFunction(this, pattern, string, start);
}
@Override
public Expression<Integer> locate(Expression<String> string, String pattern) {
return new LocateFunction(this, pattern, string);
}
@Override
public Expression<Integer> locate(Expression<String> string, String pattern, int start) {
return new LocateFunction(this, pattern, string, start);
}
@Override
public Expression<String> concat(Expression<String> string1, Expression<String> string2) {
return new ConcatFunction(this, string1, string2);
}
@Override
public Expression<String> concat(Expression<String> string1, String string2) {
return new ConcatFunction(this, string1, string2);
}
@Override
public Expression<String> concat(String string1, Expression<String> string2) {
return new ConcatFunction(this, string1, string2);
}
/**********************
* Arithmetic operations
**********************/
@Override
public <N extends Number> Expression<N> neg(Expression<N> expression) {
return new UnaryMinusExpression<N>(this, expression);
}
@Override
@SuppressWarnings({"unchecked"})
public <N extends Number> Expression<N> sum(Expression<? extends N> expression1, Expression<? extends N> expression2) {
checkExpression(expression1);
checkExpression(expression2);
final Class resultType = BinaryArithmeticExpression.determineResultType(expression1.getJavaType(), expression2.getJavaType());
return new BinaryArithmeticExpression<N>(this, resultType, BinaryArithmeticExpression.Operation.ADD, expression1, expression2);
}
@Override
@SuppressWarnings({"unchecked"})
public <N extends Number> Expression<N> prod(Expression<? extends N> expression1, Expression<? extends N> expression2) {
checkExpression(expression1);
checkExpression(expression2);
final Class resultType = BinaryArithmeticExpression.determineResultType(expression1.getJavaType(), expression2.getJavaType());
return new BinaryArithmeticExpression<N>(this, resultType, BinaryArithmeticExpression.Operation.MULTIPLY, expression1, expression2);
}
@Override
@SuppressWarnings({"unchecked"})
public <N extends Number> Expression<N> diff(Expression<? extends N> expression1, Expression<? extends N> expression2) {
checkExpression(expression1);
checkExpression(expression2);
final Class resultType = BinaryArithmeticExpression.determineResultType(expression1.getJavaType(), expression2.getJavaType());
return new BinaryArithmeticExpression<N>(this, resultType, BinaryArithmeticExpression.Operation.SUBTRACT, expression1, expression2);
}
@Override
@SuppressWarnings({"unchecked"})
public <N extends Number> Expression<N> sum(Expression<? extends N> expression, N value) {
checkValue(value);
checkExpression(expression);
final Class resultType = BinaryArithmeticExpression.determineResultType(expression.getJavaType(), value.getClass());
return new BinaryArithmeticExpression<N>(this, resultType, BinaryArithmeticExpression.Operation.ADD, expression, value);
}
@Override
@SuppressWarnings({"unchecked"})
public <N extends Number> Expression<N> prod(Expression<? extends N> expression, N value) {
checkValue(value);
checkExpression(expression);
final Class resultType = BinaryArithmeticExpression.determineResultType(expression.getJavaType(), value.getClass());
return new BinaryArithmeticExpression<N>(this, resultType, BinaryArithmeticExpression.Operation.MULTIPLY, expression, value);
}
@Override
@SuppressWarnings({"unchecked"})
public <N extends Number> Expression<N> diff(Expression<? extends N> expression, N value) {
checkValue(value);
checkExpression(expression);
final Class resultType = BinaryArithmeticExpression.determineResultType(expression.getJavaType(), value.getClass());
return new BinaryArithmeticExpression<N>(this, resultType, BinaryArithmeticExpression.Operation.SUBTRACT, expression, value);
}
@Override
@SuppressWarnings({"unchecked"})
public <N extends Number> Expression<N> sum(N value, Expression<? extends N> expression) {
checkValue(value);
checkExpression(expression);
final Class resultType = BinaryArithmeticExpression.determineResultType(value.getClass(), expression.getJavaType());
return new BinaryArithmeticExpression<N>(this, resultType, BinaryArithmeticExpression.Operation.ADD, value, expression);
}
@Override
@SuppressWarnings({"unchecked"})
public <N extends Number> Expression<N> prod(N value, Expression<? extends N> expression) {
checkValue(value);
checkExpression(expression);
final Class resultType = BinaryArithmeticExpression.determineResultType(value.getClass(), expression.getJavaType());
return (BinaryArithmeticExpression<N>) new BinaryArithmeticExpression(this, resultType, BinaryArithmeticExpression.Operation.MULTIPLY, value, expression);
}
@Override
@SuppressWarnings({"unchecked"})
public <N extends Number> Expression<N> diff(N value, Expression<? extends N> expression) {
checkValue(value);
checkExpression(expression);
final Class resultType = BinaryArithmeticExpression.determineResultType(value.getClass(), expression.getJavaType());
return new BinaryArithmeticExpression<N>(this, resultType, BinaryArithmeticExpression.Operation.SUBTRACT, value, expression);
}
@Override
@SuppressWarnings({"unchecked"})
public Expression<Number> quot(Expression<? extends Number> expression1, Expression<? extends Number> expression2) {
checkExpression(expression1);
checkExpression(expression2);
final Class resultType = BinaryArithmeticExpression.determineResultType(expression1.getJavaType(), expression2.getJavaType(), true);
return new BinaryArithmeticExpression<Number>(this, resultType, BinaryArithmeticExpression.Operation.DIVIDE, expression1, expression2);
}
@Override
@SuppressWarnings({"unchecked"})
public Expression<Number> quot(Expression<? extends Number> expression, Number value) {
checkValue(value);
checkExpression(expression);
final Class resultType = BinaryArithmeticExpression.determineResultType(expression.getJavaType(), value.getClass(), true);
return new BinaryArithmeticExpression<Number>(this, resultType, BinaryArithmeticExpression.Operation.DIVIDE, expression, value);
}
@Override
@SuppressWarnings({"unchecked"})
public Expression<Number> quot(Number value, Expression<? extends Number> expression) {
checkValue(value);
checkExpression(expression);
final Class resultType = BinaryArithmeticExpression.determineResultType(value.getClass(), expression.getJavaType(), true);
return new BinaryArithmeticExpression<Number>(this, resultType, BinaryArithmeticExpression.Operation.DIVIDE, value, expression);
}
@Override
public Expression<Integer> mod(Expression<Integer> expression1, Expression<Integer> expression2) {
checkExpression(expression1);
checkExpression(expression2);
return new BinaryArithmeticExpression<Integer>(this, Integer.class, BinaryArithmeticExpression.Operation.MOD, expression1, expression2);
}
@Override
public Expression<Integer> mod(Expression<Integer> expression, Integer value) {
checkValue(value);
checkExpression(expression);
return new BinaryArithmeticExpression<Integer>(this, Integer.class, BinaryArithmeticExpression.Operation.MOD, expression, value);
}
@Override
public Expression<Integer> mod(Integer value, Expression<Integer> expression) {
checkValue(value);
checkExpression(expression);
return new BinaryArithmeticExpression<Integer>(this, Integer.class, BinaryArithmeticExpression.Operation.MOD, value, expression);
}
private void checkValue(Object value) {
if (value == null) {
throw new IllegalArgumentException("null value not allowed!");
}
}
private void checkExpression(Expression<?> expression) {
if (expression == null) {
throw new IllegalArgumentException("null expression not allowed!");
}
}
/**********************
* Casting functions
**********************/
@Override
@SuppressWarnings({"unchecked"})
public Expression<Long> toLong(Expression<? extends Number> expression) {
return ((AbstractExpression<? extends Number>) expression).asLong();
}
@Override
@SuppressWarnings({"unchecked"})
public Expression<Integer> toInteger(Expression<? extends Number> expression) {
return ((AbstractExpression<? extends Number>) expression).asInteger();
}
@Override
@SuppressWarnings({"unchecked"})
public Expression<Float> toFloat(Expression<? extends Number> expression) {
return ((AbstractExpression<? extends Number>) expression).asFloat();
}
@Override
@SuppressWarnings({"unchecked"})
public Expression<Double> toDouble(Expression<? extends Number> expression) {
return ((AbstractExpression<? extends Number>) expression).asDouble();
}
@Override
@SuppressWarnings({"unchecked"})
public Expression<BigDecimal> toBigDecimal(Expression<? extends Number> expression) {
return ((AbstractExpression<? extends Number>) expression).asBigDecimal();
}
@Override
@SuppressWarnings({"unchecked"})
public Expression<BigInteger> toBigInteger(Expression<? extends Number> expression) {
return ((AbstractExpression<? extends Number>) expression).asBigInteger();
}
@Override
public Expression<String> toString(Expression<Character> characterExpression) {
return ((AbstractExpression<Character>) characterExpression).asString();
}
/**********************
* Subquery expressions
**********************/
@Override
public Predicate exists(Subquery<?> subquery) {
return new ExistsPredicate(this, subquery);
}
@Override
@SuppressWarnings({"unchecked"})
public <Y> Expression<Y> all(Subquery<Y> subquery) {
return new QuantifiableSubqueryExpression<Y>(this, (Class<Y>) subquery.getJavaType(), subquery, QuantifiableSubqueryExpression.Quantor.ALL);
}
@Override
@SuppressWarnings({"unchecked"})
public <Y> Expression<Y> some(Subquery<Y> subquery) {
return new QuantifiableSubqueryExpression<Y>(this, (Class<Y>) subquery.getJavaType(), subquery, QuantifiableSubqueryExpression.Quantor.SOME);
}
@Override
@SuppressWarnings({"unchecked"})
public <Y> Expression<Y> any(Subquery<Y> subquery) {
return new QuantifiableSubqueryExpression<Y>(this, (Class<Y>) subquery.getJavaType(), subquery, QuantifiableSubqueryExpression.Quantor.ANY);
}
/**********************
* Case-When stuff
**********************/
@Override
public <Y> Expression<Y> coalesce(Expression<? extends Y> exp1, Expression<? extends Y> exp2) {
return coalesce((Class<Y>) null, exp1, exp2);
}
public <Y> Expression<Y> coalesce(Class<Y> type, Expression<? extends Y> exp1, Expression<? extends Y> exp2) {
return new CoalesceFunction<Y>(this, type).value(exp1).value(exp2);
}
@Override
public <Y> Expression<Y> coalesce(Expression<? extends Y> exp1, Y exp2) {
return coalesce((Class<Y>) null, exp1, exp2);
}
public <Y> Expression<Y> coalesce(Class<Y> type, Expression<? extends Y> exp1, Y exp2) {
return new CoalesceFunction<Y>(this, type).value(exp1).value(exp2);
}
@Override
public <T> Coalesce<T> coalesce() {
return coalesce((Class<T>) null);
}
public <T> Coalesce<T> coalesce(Class<T> type) {
return new CoalesceFunction<T>(this, type);
}
@Override
public <Y> Expression<Y> nullif(Expression<Y> exp1, Expression<?> exp2) {
return nullif(null, exp1, exp2);
}
public <Y> Expression<Y> nullif(Class<Y> type, Expression<Y> exp1, Expression<?> exp2) {
return new NullifFunction<Y>(this, type, exp1, exp2);
}
@Override
public <Y> Expression<Y> nullif(Expression<Y> exp1, Y exp2) {
return nullif(null, exp1, exp2);
}
public <Y> Expression<Y> nullif(Class<Y> type, Expression<Y> exp1, Y exp2) {
return new NullifFunction<Y>(this, type, exp1, exp2);
}
@Override
public <C, R> SimpleCase<C, R> selectCase(Expression<? extends C> expression) {
// JDK 9 complains without the cast
return /*(SimpleCase<C, R>) */selectCase((Class<R>) null, expression);
}
public <C, R> SimpleCase<C, R> selectCase(Class<R> type, Expression<? extends C> expression) {
return new SimpleCaseExpression<C, R>(this, type, expression);
}
@Override
public <R> Case<R> selectCase() {
return selectCase((Class<R>) null);
}
public <R> Case<R> selectCase(Class<R> type) {
return new GeneralCaseExpression<R>(this, type);
}
/**********************
* Collection functions
**********************/
@Override
public <C extends Collection<?>> Expression<Integer> size(C c) {
int size = c == null ? 0 : c.size();
return new LiteralExpression<Integer>(this, Integer.class, size);
}
@Override
public <C extends Map<?, ?>> Expression<Integer> mapSize(C c) {
int size = c == null ? 0 : c.size();
return new LiteralExpression<Integer>(this, Integer.class, size);
}
@Override
public <C extends Collection<?>> Expression<Integer> size(Expression<C> exp) {
if (LiteralExpression.class.isInstance(exp)) {
return size(((LiteralExpression<C>) exp).getLiteral());
} else if (PluralAttributePath.class.isInstance(exp)) {
return new SizeFunction(this, (PluralAttributePath<C>) exp);
}
throw illegalCollection(exp);
}
@Override
public <C extends Map<?, ?>> Expression<Integer> mapSize(Expression<C> exp) {
if (LiteralExpression.class.isInstance(exp)) {
return mapSize(((LiteralExpression<C>) exp).getLiteral());
} else if (PluralAttributePath.class.isInstance(exp)) {
return new SizeFunction(this, (PluralAttributePath<C>) exp);
}
throw illegalCollection(exp);
}
@Override
public <V, M extends Map<?, V>> Expression<Collection<V>> values(M map) {
return new LiteralExpression<Collection<V>>(this, map.values());
}
@Override
public <K, M extends Map<K, ?>> Expression<Set<K>> keys(M map) {
return new LiteralExpression<Set<K>>(this, map.keySet());
}
@Override
@SuppressWarnings({"unchecked"})
public <C extends Collection<?>> Predicate isEmpty(Expression<C> collectionExpression) {
if (!(collectionExpression instanceof PluralAttributePath<?>)) {
throw illegalCollection(collectionExpression);
}
return new IsEmptyPredicate(this, false, (PluralAttributePath<C>) collectionExpression);
}
@Override
@SuppressWarnings({"unchecked"})
public <C extends Map<?, ?>> Predicate isMapEmpty(Expression<C> collectionExpression) {
if (!(collectionExpression instanceof PluralAttributePath<?>)) {
throw illegalCollection(collectionExpression);
}
return new IsEmptyPredicate(this, false, (PluralAttributePath<C>) collectionExpression);
}
@Override
@SuppressWarnings({"unchecked"})
public <C extends Collection<?>> Predicate isNotEmpty(Expression<C> collectionExpression) {
if (!(collectionExpression instanceof PluralAttributePath<?>)) {
throw illegalCollection(collectionExpression);
}
return new IsEmptyPredicate(this, true, (PluralAttributePath<C>) collectionExpression);
}
@Override
@SuppressWarnings({"unchecked"})
public <C extends Map<?, ?>> Predicate isMapNotEmpty(Expression<C> collectionExpression) {
if (!(collectionExpression instanceof PluralAttributePath<?>)) {
throw illegalCollection(collectionExpression);
}
return new IsEmptyPredicate(this, true, (PluralAttributePath<C>) collectionExpression);
}
@Override
public <E, C extends Collection<E>> Predicate isMember(E e, Expression<C> collectionExpression) {
if (!(collectionExpression instanceof PluralAttributePath<?>)) {
throw illegalCollection(collectionExpression);
}
return new MemberOfPredicate<E, C>(this, false, e, (PluralAttributePath<C>) collectionExpression);
}
@Override
public <E, C extends Collection<E>> Predicate isNotMember(E e, Expression<C> collectionExpression) {
if (!(collectionExpression instanceof PluralAttributePath<?>)) {
throw illegalCollection(collectionExpression);
}
return new MemberOfPredicate<E, C>(this, true, e, (PluralAttributePath<C>) collectionExpression);
}
@Override
public <E, C extends Collection<E>> Predicate isMember(Expression<E> elementExpression, Expression<C> collectionExpression) {
if (!(collectionExpression instanceof PluralAttributePath<?>)) {
throw illegalCollection(collectionExpression);
}
return new MemberOfPredicate<E, C>(this, false, elementExpression, (PluralAttributePath<C>) collectionExpression);
}
@Override
public <E, C extends Collection<E>> Predicate isNotMember(Expression<E> elementExpression, Expression<C> collectionExpression) {
if (!(collectionExpression instanceof PluralAttributePath<?>)) {
throw illegalCollection(collectionExpression);
}
return new MemberOfPredicate<E, C>(this, true, elementExpression, (PluralAttributePath<C>) collectionExpression);
}
private RuntimeException illegalCollection(Expression<?> expression) {
return new IllegalArgumentException("Illegal expression type! Expected plural expression but got: " + expression.getClass().getName());
}
/****************************
* Treat support for JPA 2.1
***************************/
@Override
public <X, T, V extends T> BlazeJoin<X, V> treat(Join<X, T> join, Class<V> type) {
return ((AbstractJoin<X, T>) join).treatJoin(type);
}
@Override
public <X, T, E extends T> BlazeCollectionJoin<X, E> treat(CollectionJoin<X, T> join, Class<E> type) {
return ((CollectionAttributeJoin<X, T>) join).treatJoin(type);
}
@Override
public <X, T, E extends T> BlazeSetJoin<X, E> treat(SetJoin<X, T> join, Class<E> type) {
return ((SetAttributeJoin<X, T>) join).treatJoin(type);
}
@Override
public <X, T, E extends T> BlazeListJoin<X, E> treat(ListJoin<X, T> join, Class<E> type) {
return ((ListAttributeJoin<X, T>) join).treatJoin(type);
}
@Override
public <X, K, T, V extends T> BlazeMapJoin<X, K, V> treat(MapJoin<X, K, T> join, Class<V> type) {
return ((MapAttributeJoin<X, K, T>) join).treatJoin(type);
}
@Override
public <X, T extends X> Path<T> treat(Path<X> path, Class<T> type) {
if (path instanceof AbstractJoin<?, ?>) {
return ((AbstractJoin<?, X>) path).treatJoin(type);
}
return ((AbstractPath<X>) path).treatAs(type);
}
@Override
public <X, T extends X> BlazeRoot<T> treat(Root<X> root, Class<T> type) {
return ((RootImpl<X>) root).treatAs(type);
}
}